package com.biz.primus.ms.member.dao.redis;

import com.biz.primus.base.redis.CrudRedisDao;
import com.biz.primus.base.redis.util.RedisUtil;
import com.biz.primus.ms.member.dao.ro.NoticeRo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;

import java.sql.Timestamp;
import java.util.List;
import java.util.Set;

/**
 * @author jun.liu
 * @date 2017年10月23日
 * @reviewer
 * @see
 */
@Repository
public class NoticeRedisDao extends CrudRedisDao<NoticeRo, Long> {


    /**
     * 用户的 公告sortedset key NoticeRo:user:{userId}
     * @author jun.liu
     * @reviewer
     * @see
     */
    public String getUserNoticeSortedSetKey(Long userId) {
        return super.getKeyByParams("user", userId);
    }

    /**
     * 给所有人公共 key NoticeRo:everyone:{userId}
     * @author jun.liu
     * @reviewer
     * @see
     */
    public String getToEveryOneNoticeSortedSetKey() {
        return super.getKeyByParams("everyone");
    }

    /**
     * 用户最后一条通知Id，主要用于过滤公告消息 key NoticeRo:last:{userId}
     * @author jun.liu
     * @reviewer
     * @see
     */
    public String getUserLastNoticeStringKey(Long userId) {
        return super.getKeyByParams("last", userId);
    }

    /**
     * 分页获取所有的消息(暂只获取向所有用户推送的消息)
     * @author jun.liu
     * @param page 0为第一页
     * @param size
     */
    public List<NoticeRo> getAllNotice(int page, int size) {
        //因为该方法中page=1为第一页，所以要加1
        return super.findByScoreDesc(page + 1, size);
    }

    /**
     * 将消息Id增加到某个用户的SortedSet中
     * @author jun.liu
     */
    public void sendToUser(Long noticeId, Timestamp ts, Long userId) {
        super.zadd(getUserNoticeSortedSetKey(userId), ts.getTime(), RedisUtil.toByteArray(noticeId));
    }

    /**
     * 将通知Id增加到一批用户的SortedSet中
     * @author jun.liu
     */
    public void sendToUsers(Long noticeId, Timestamp ts, List<Long> userIds) {
        if (CollectionUtils.isNotEmpty(userIds)) {
            for (Long userId : userIds) {
                sendToUser(noticeId, ts, userId);
            }
        }
    }

    /**
     * 给所有人
     * @author jun.liu
     * @reviewer
     * @see
     */
    public void sendToEveryOne(Long noticeId) {
        super.zadd(getToEveryOneNoticeSortedSetKey(), System.currentTimeMillis(), RedisUtil.toByteArray(noticeId));
    }

    /**
     * 将所有用户的通知Id从SortedSet中移除
     * @param noticeId
     * @author jun.liu
     */
    public void removeNoticeIdOfAllUsersFromSortedSet(Long noticeId) {
        super.zrem(getToEveryOneNoticeSortedSetKey(), RedisUtil.toByteArray(noticeId));
    }

    public List<NoticeRo> getUserRemain(Long userId) {
        Set<String> ids = zrangeByScore(getUserNoticeSortedSetKey(userId), "-inf", "+inf");
        if (CollectionUtils.isNotEmpty(ids)) {
            return super.findByStrIds(ids);
        }
        return null;
    }

    public Long getUserRemainNoticeCount(Long userId) {
        return zCard(getUserNoticeSortedSetKey(userId));
    }

    public List<NoticeRo> getEveryOneRemainNotices(Long ts) {
        Set<String> ids = zrangeByScore(getToEveryOneNoticeSortedSetKey(), "(" + ts, "+inf");
        if (CollectionUtils.isNotEmpty(ids)) {
            return super.findByStrIds(ids);
        }
        return null;
    }

    public Long getEveryOneRemainNoticeCount(Long ts) {
        return super.zcount(getToEveryOneNoticeSortedSetKey(), "(" + ts, "+inf");
    }

    public void deleteUserNotice(Long userId) {
        super.zremrangeByScore(getUserNoticeSortedSetKey(userId), "-inf", "+inf");
    }

    public Long getUserLastReceiveTs(Long userId) {
        byte[] ts = get(getUserLastNoticeStringKey(userId));
        if (ts != null) {
            return RedisUtil.byteArrayToLong(ts);
        } else {
            return null;
        }
    }

    public void setUserLastReceiveTs(Long userId, Long ts) {
        set(getUserLastNoticeStringKey(userId), RedisUtil.toByteArray(ts));
    }
}
